package cn.ztuo.bitrade.job;


import cn.ztuo.bitrade.constant.TransactionType;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.service.*;
import cn.ztuo.bitrade.util.BigDecimalUtils;
import cn.ztuo.bitrade.util.FiworkWalletUtil;
import cn.ztuo.bitrade.util.RedisUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class EthAutoArrive {

    @Autowired
    private CoinService coinService;
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    private MemberDepositService memberDepositService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private MemberTransactionService memberTransactionService;

    private static String COINNAME = "ETH";
    private static String BLOCKNUM = "1000";

    /**
     * 定义开始区块，请求ETH交易信息
     * @param address 提币地址
     * @param startBlock 开始区块
     * @return
     */
    private JSONObject sendRequest(String address,String startBlock){
            return FiworkWalletUtil.getEthRecorded(address,startBlock,"99999999");
    }

    /**
     * 获取ETH最高区块
     * @param key 获取存储Redis的区块key
     * @return
     * @throws IOException
     */
    private String getBlockNumber(String key) throws IOException {
            if (!redisUtil.hasKey(key)) {
                redisUtil.set(key, String.valueOf(FiworkWalletUtil.getBlockNumber()));
            }
            return String.valueOf(redisUtil.get(key));
    }

    private void setBlockNumber(String key) throws IOException {
        redisUtil.set(key, String.valueOf(FiworkWalletUtil.getBlockNumber()));
    }


    /**
     * ETH到账方法
     */
    @Async("taskEthExecutor")
//    @Scheduled(fixedDelay =5* 60 * 1000)
    public void AutoArrive(){
       Coin coin = coinService.findByUnit(COINNAME);
       List<MemberWallet> memberInfos  = memberWalletService.selectCoininfo(coin.getUnit());
       if(memberInfos!=null && memberInfos.size()>0){
           log.info("ETH查询到账开始运行");
           memberInfos.stream().filter(wallt-> StringUtils.isNotEmpty(wallt.getAddress())).forEach(wallet->{
               JSONObject jsonObject = null;
               try {
                   String startBlock = String.valueOf(BigDecimalUtils.sub(new BigDecimal(getBlockNumber(COINNAME+"_BLOCK_NUMBER")),new BigDecimal(BLOCKNUM)));
                   jsonObject =  sendRequest(wallet.getAddress(), startBlock);
               } catch (IOException e) {
                   e.printStackTrace();
               }
               if ("OK".equals(jsonObject.getString("message")) && 1 == jsonObject.getInteger("status") && jsonObject.get("result") != null) {
                   JSONArray jsonArray  = jsonObject.getJSONArray("result");
                   List<JSONObject> resultList = jsonArray.toJavaList(JSONObject.class);
                   if (resultList != null && resultList.size() > 0) {
                       resultList.forEach(result -> {
                           BigDecimal value = result.getBigDecimal("value");
                           if (value.compareTo(BigDecimal.ZERO) > 0) {
                               // 获取到入账地址 比对 命中时去数据库中查询该txid是否已经记录 如已经记录则跳过，否则入账该记录
                               String toAddress = result.getString("to");
                               String fromAddress = result.getString("from");
                               if (wallet.getAddress().equalsIgnoreCase(toAddress)) {
                                   String txid = result.getString("hash");
                                   if (memberDepositService.findTxid(toAddress,txid) == false) {
                                       BigDecimal amount = BigDecimalUtils.div(value, new BigDecimal("1000000000000000000"));
                                       if (amount.compareTo(coin.getMinRechargeAmount()) >= 0) {
                                           MemberDeposit depositRecord = new MemberDeposit();
                                           depositRecord.setAddress(toAddress);
                                           depositRecord.setAmount(amount);
                                           depositRecord.setTxid(txid);
                                           depositRecord.setMemberId(wallet.getMemberId());
                                           depositRecord.setUnit(COINNAME);
                                           depositRecord.setCreateTime(new Date());
                                           Member member =memberService.findOne(wallet.getMemberId());
                                           depositRecord.setUsername(member.getUsername());
                                           memberDepositService.save(depositRecord);
                                           memberWalletService.increaseBalance2(wallet.getId(),amount);
                                            //充值到账记录
                                           MemberTransaction transaction = new MemberTransaction();
                                           transaction.setAmount(amount);
                                           transaction.setSymbol("ETH");
                                           transaction.setAddress(fromAddress);
                                           transaction.setMemberId(wallet.getMemberId());
                                           transaction.setType(TransactionType.RECHARGE);
                                           transaction.setFee(BigDecimal.ZERO);
                                           transaction.setCreateTime(new Date());
                                           transaction.setRemark("充值");
                                           memberTransactionService.save(transaction);

                                       } else {
                                           log.info("------ 已查询出充值到账记录，但不满足最小充值数量！------ 数量为：" + amount + "；------ 币种为：" + coin.getName());
                                       }
                                   }
                               }
                           }
                       });
                   }
               }
           });
           // 获取最新区块存入REDIS
           try {
               setBlockNumber(COINNAME+"_BLOCK_NUMBER");
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
        log.info("ETH查询到账运行成功");
    }

}
